package cn.com.cifi.mars.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.com.cifi.mars.bean.dto.DmDmContractMonthDto;
import cn.com.cifi.mars.bean.dto.MymContractDto;
import cn.com.cifi.mars.bean.dto.NosTradedataDto;
import cn.com.cifi.mars.bean.dto.ProjectByStagesDto;
import cn.com.cifi.mars.bean.vo.supply.ContractVO;
import cn.com.cifi.mars.bean.vo.supply.MonthInventoryVO;
import cn.com.cifi.mars.bean.vo.supply.MonthSupplyVO;
import cn.com.cifi.mars.bean.vo.supply.NosSignVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyMonthlyBaseValueVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyMonthlyDetailVO;
import cn.com.cifi.mars.constant.ActivationEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.SalyTypeEnum;
import cn.com.cifi.mars.constant.StageStatusEnum;
import cn.com.cifi.mars.constant.TradeStatusEnum;
import cn.com.cifi.mars.constant.VersionAttrEnum;
import cn.com.cifi.mars.constant.VersionIdentifyEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.entity.DmDmSupplyMonthlyDetail;
import cn.com.cifi.mars.entity.DmDmValueReport;
import cn.com.cifi.mars.entity.SupplyPlanVersion;
import cn.com.cifi.mars.entity.SupplyPlanVersionDetail;
import cn.com.cifi.mars.entity.common.ProjectByStages;
import cn.com.cifi.mars.mapper.mars.DmDmSupplyCompareDetailMapper;
import cn.com.cifi.mars.mapper.mars.DmDmSupplyMonthlyDetailMapper;
import cn.com.cifi.mars.mapper.mars.SupplyPlanVersionDetailMapper;
import cn.com.cifi.mars.service.DmDmSupplyMonthlyDetailService;
import cn.com.cifi.mars.service.IdmUserService;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.NumberUtils;
import cn.com.cifi.mars.util.StrUtils;
import cn.com.cifi.mars.util.UUIDUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 月度供货明细表 服务实现类
 * </p>
 *
 * @author yyd
 * @since 2020-02-24
 */
@Slf4j
@Service
public class DmDmSupplyMonthlyDetailServiceImpl extends ServiceImpl<DmDmSupplyMonthlyDetailMapper, DmDmSupplyMonthlyDetail> implements DmDmSupplyMonthlyDetailService {
	
	@Autowired
	private SupplyPlanVersionDetailMapper supplyPlanVersionDetailMapper;
	
	@Autowired
	private DmDmSupplyCompareDetailMapper dmDmSupplyCompareDetailMapper;
	
	@Autowired
	private DmDmSupplyMonthlyDetailMapper dmDmSupplyMonthlyDetailMapper;
	
	@Autowired
	private IdmUserService idmUserService;
	
	@Override
	public List<DmDmValueReport> selectReportList(String deadline) {
		return  dmDmSupplyMonthlyDetailMapper.selectReportList(deadline);
	}
	
	/**
	 * 
	 * @Description：月度供货明细表数据初始化
	 * @author：yyd
	 * @date：2020年2月25日 下午4:08:17
	 */
	@Override
	public void initSupplyMonthlyDetailReport(String yearMonth,String projectIdStr) {
		List<String> months =  Arrays.asList(yearMonth);
		if(StrUtils.isNotEmpty(projectIdStr)) {
			int count = dmDmSupplyMonthlyDetailMapper.removeMonthDataByProjectId(yearMonth,projectIdStr);
		}else {
			int count = dmDmSupplyMonthlyDetailMapper.removeMonthData(yearMonth);
		}
		List<DmDmValueReport> reportList  = dmDmSupplyMonthlyDetailMapper.selectReportList(yearMonth);
    	//查询所有版本详情数据
    	List<SupplyPlanVersionDetail> allVersionDetailList = supplyPlanVersionDetailMapper.selectAllList(IsDeleteEnum.NO.getKey());
        //签约数据
    	List<DmDmContractMonthDto> contractList = dmDmSupplyMonthlyDetailMapper.selectContractList();
        
		for(String versionMonth : months) {
			//获取月份全盘最新货值版本对应的供货版本
			List<SupplyPlanVersion> versionList = dmDmSupplyMonthlyDetailMapper.selectAllVersionList(versionMonth,IsDeleteEnum.NO.getKey());
			for(SupplyPlanVersion version : versionList) {
				long handleStart = System.currentTimeMillis();
				List<DmDmSupplyMonthlyDetail> dataList = Collections.synchronizedList(new ArrayList<>());
				if(version != null) {
					String projectId = version.getProjectId();
					if(StrUtils.isNotEmpty(projectIdStr) && !projectId.equals(projectIdStr)) {
						continue;
					}
		    		String versionId = version.getId();
		    		String versionType = version.getVersionType();
		    		String versionAttr = version.getVersionAttr();
		    		List<SupplyPlanVersionDetail> versionDetailList = prepareVersionDetail(projectId,versionId,versionType,versionAttr,allVersionDetailList);
		    		
		    		List<Integer> yearSet = getYear(versionDetailList);
		    		List<String> versionMonths = getMonthsTwo(yearSet);
			        for(String monthStr : versionMonths) {
			    		//月初库存计算
			    		List<MonthInventoryVO> inventoryList = Collections.synchronizedList(new ArrayList<>());
			    		List<MonthInventoryVO> actualInventoryList = Collections.synchronizedList(new ArrayList<>());
			    		if(isBeforeStrategy(versionType,versionAttr)) {
			    			List<DmDmSupplyMonthlyDetail> resList = saveData(versionDetailList,version,inventoryList,actualInventoryList,versionMonth,monthStr,true,reportList);
			    			dataList.addAll(resList);
			    		}else {
					        //供货日期早于当前月楼栋
					        List<SupplyPlanVersionDetail> buildList = preparebuildList(versionDetailList,monthStr);
					        //实际供货日期早于当前月楼栋
					        List<SupplyPlanVersionDetail> actualBuildList = prepareActualbuildList(versionDetailList,monthStr);
					        //实际签约数据
				            List<ContractVO> signList = prepareSignList(contractList,buildList,monthStr);
				            
				            List<ContractVO> signActualList = prepareSignList(contractList,actualBuildList,monthStr);
					        
					        //供货数据
				            List<MonthSupplyVO> supplyList = prepareSupplyList(buildList,monthStr);
				            
				            List<MonthSupplyVO> actualSupplyList = prepareSupplyList(actualBuildList,monthStr);
					        
					        //计算月初存货
				            inventoryList = getMonthInventoryList(signList,supplyList,monthStr);
				            
				            actualInventoryList = getMonthInventoryList(signActualList,actualSupplyList,monthStr);
					        
			    			versionDetailList = handleAfterStrategyData(versionDetailList,projectId);
			    			List<DmDmSupplyMonthlyDetail> resList = saveData(versionDetailList,version,inventoryList,actualInventoryList,versionMonth,monthStr,false,reportList);
			    			dataList.addAll(resList);
			    		}
					}
			        if(CollectionUtils.isNotEmpty(dataList)) {
			        	dmDmSupplyMonthlyDetailMapper.insertBatch(dataList);
			        	long handleEnd = System.currentTimeMillis();
			        	log.info("处理"+versionMonth+"月份对应的版本数据（版本ID："+versionId+"），计算存货、实际存货、计划、实际数据，并保存数据，耗时："+(handleEnd-handleStart));
			        }
				}
			}
		}
		
		//添加最新版数据
		String newestDate = dmDmSupplyMonthlyDetailMapper.selectMaxVersionDate(yearMonth);
		String yearStr = newestDate.split("-")[0];
		String monthStr = newestDate.split("-")[1];
		int count = dmDmSupplyMonthlyDetailMapper.removeMonthNewestData(newestDate);
		dmDmSupplyMonthlyDetailMapper.insertSyncNewest(newestDate,yearStr,monthStr,StageStatusEnum.CTIVE.getKey());
		
	}

	private List<SupplyPlanVersionDetail> prepareVersionDetail(String projectId,String versionId,String versionType,
			String versionAttr,List<SupplyPlanVersionDetail> allVersionDetailList) {
		
		List<SupplyPlanVersionDetail> list = Collections.synchronizedList(new ArrayList<>());
		for(SupplyPlanVersionDetail detail : allVersionDetailList) {
			if(detail.getVersionId().equals(versionId)) {
				list.add(detail);
			}
		}
		if(isBeforeStrategy(versionType,versionAttr)) {
			//战规前处理
			List<SupplyPlanVersionDetail>  brforeList = handleBeforeStrategyData(list,projectId);
			prepareProProductLevel(brforeList);
			
			return handleValidData(brforeList);
		}
		//添加业态层级
		prepareProProductLevel(list);
		
		return handleValidData(list);
	}
	
	private void prepareProProductLevel(List<SupplyPlanVersionDetail> resList) {
		List<SupplyPlanVersionDetail> list = Collections.synchronizedList(new ArrayList<>());
		Map<String, Object> map = new HashMap<>();
		if(CollectionUtils.isNotEmpty(resList)) {
			for(SupplyPlanVersionDetail vo : resList) {
				if(StrUtils.isNotEmpty(vo.getType()) && vo.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
					String orgFullPathName = vo.getOrgFullPathName();
					String proOrgFullPathName = orgFullPathName.substring(0, orgFullPathName.lastIndexOf("/"));
					map.put(proOrgFullPathName, vo);
				}
			}
		}
		
		for(Map.Entry<String, Object> entry : map.entrySet()){
		    String mapKey = entry.getKey();
		    SupplyPlanVersionDetail mapValue = (SupplyPlanVersionDetail) entry.getValue();
		    boolean isValid = checkSupplyPlanVersionDetail(mapKey,resList);
		    if(isValid) {
		    	  SupplyPlanVersionDetail proObj = new SupplyPlanVersionDetail();
				    String id= UUIDUtils.create();
				    proObj.setId(id);
					proObj.setVersionId(mapValue.getVersionId());
					proObj.setOrgCode(mapValue.getProProductCode());
					proObj.setOrgName(mapValue.getProProductType());
					proObj.setPid(mapValue.getPid());
					proObj.setType(OrgTypeEunm.ORG_PRO_TYPE.getKey());
					proObj.setOrgFullPathName(mapKey);
					proObj.setIsDelete(IsDeleteEnum.NO.getKey());
					list.add(proObj);
		    }
		}
		
		if(CollectionUtils.isNotEmpty(resList)) {
			for(SupplyPlanVersionDetail vo : resList) {
				if(StrUtils.isNotEmpty(vo.getType()) && vo.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
					String orgFullPathName = vo.getOrgFullPathName();
					for(SupplyPlanVersionDetail vo2 : list) {
						String proOrgFullPathName = vo2.getOrgFullPathName();
						if(orgFullPathName.contains(proOrgFullPathName)) {
							vo.setPid(vo2.getId());
						}
					}
				}
			}
		}
		resList.addAll(list);
	}
	

	private boolean checkSupplyPlanVersionDetail(String mapKey, List<SupplyPlanVersionDetail> resList) {
		for(SupplyPlanVersionDetail detail : resList) {
			String orgFullPathName = detail.getOrgFullPathName(); 
			String businessType = detail.getBusinessType();
			if(orgFullPathName.contains(mapKey) && StrUtils.isNotEmpty(businessType) && isValid(businessType)) {
				return true;
			}
		}
		return false;
	}

	private List<SupplyPlanVersionDetail>  handleValidData(List<SupplyPlanVersionDetail> list) {
		List<SupplyPlanVersionDetail> resList = Collections.synchronizedList(new ArrayList<>());
		//去除经营方式为不可租售和可租数据
		for(SupplyPlanVersionDetail supplyPlanVersionDetail : list) {
			String businessType = supplyPlanVersionDetail.getBusinessType();
			if(StrUtils.isEmpty(businessType)) {
				//判断是否有子级
				boolean flag = hasChild(list,supplyPlanVersionDetail.getId());
				if(flag && isValidData(list,supplyPlanVersionDetail.getId())) {
					resList.add(supplyPlanVersionDetail);
				}
			}else{
				if(isValid(businessType)) {
					resList.add(supplyPlanVersionDetail);
				}
			}
		}
		return resList;
	}
	
	private boolean hasChild(List<SupplyPlanVersionDetail> list,String id) {
		boolean flag = false;
		for(SupplyPlanVersionDetail supplyPlanVersionDetail : list) {
			String pid = supplyPlanVersionDetail.getPid();
			if(pid.equals(id)) {
				flag = true;
				break;
			}
		}
		return  flag;
	}
	
	private boolean isValidData(List<SupplyPlanVersionDetail> list,String id) {
		boolean flag = false;
		for(SupplyPlanVersionDetail supplyPlanVersionDetail : list) {
			String pid = supplyPlanVersionDetail.getPid();
			String businessType = supplyPlanVersionDetail.getBusinessType();
			if(pid.equals(id)) {
				if(StrUtils.isEmpty(businessType) || isValid(businessType)) {
					flag = true;
					break;
				}
			}
		}
		return  flag;
	}
	

	public List<Integer> getYear(List<SupplyPlanVersionDetail> versionDetailList) {
		List<Integer> yearList =  new ArrayList<>();
		List<Integer> lastlist = new ArrayList<>();
		if(CollectionUtils.isNotEmpty(versionDetailList)) {
			versionDetailList.forEach(x->{
				if(x != null) {
					LocalDateTime supplyDate = x.getSupplyDate();
					LocalDateTime supplyDateActual = x.getSupplyTimeVirtual() == null ? x.getSupplyDateActual() : x.getSupplyTimeVirtual();
					if(supplyDate != null) {
						yearList.add(supplyDate.getYear());
					}
					if(supplyDateActual != null) {
						yearList.add(supplyDateActual.getYear());
					}
				}
			});
		}
		
		List<Integer> uniqueList = yearList.stream().distinct().collect(Collectors.toList());
		if(CollectionUtils.isNotEmpty(uniqueList)) {
			if(uniqueList.size() > 1) {
				Collections.sort(uniqueList);
				Integer minYear = uniqueList.get(0);
				Integer maxYear = uniqueList.get(uniqueList.size()-1);
				int curYear = LocalDateTime.now().getYear();
				int diff = 0 ;
				if(maxYear.intValue() < curYear) {
					diff = curYear - minYear.intValue();
				}else {
					diff = maxYear.intValue() - minYear.intValue();
				}
				for(int i = 0; i <= diff; i++) {
					lastlist.add(minYear.intValue() + i);
				}
			}else {
				Integer minYear = uniqueList.get(0);
				Integer maxYear = uniqueList.get(0);
				int curYear = LocalDateTime.now().getYear();
				int diff = 0 ;
				if(maxYear.intValue() < curYear) {
					diff = curYear - minYear.intValue();
					for(int i = 0; i <= diff; i++) {
						lastlist.add(minYear.intValue() + i);
					}
				}else {
					return uniqueList;
				}
			}
		}
		
		return lastlist;
	}
	
	/**
	 * 
	 * @Description：供货日期早于当前月楼栋
	 * @author：yyd
	 * @date：2020年3月6日 下午3:30:26
	 */
	private List<SupplyPlanVersionDetail> preparebuildList(List<SupplyPlanVersionDetail> allBuildList, String month) {
		List<SupplyPlanVersionDetail> resList = Collections.synchronizedList(new ArrayList<>());
		int yearMonth = LocalDateTimeUtils.toIntYearMonth(Integer.parseInt(month.split("-")[0]), Integer.parseInt(month.split("-")[1]));
		for(SupplyPlanVersionDetail detail : allBuildList) {
			 String type = detail.getType();
			 if(type.equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				if(StrUtils.isNotEmpty(detail.getBusinessType()) && isValid(detail.getBusinessType())) {
					LocalDateTime actualTime = detail.getSupplyTimeVirtual() == null ? detail.getSupplyDateActual() : detail.getSupplyTimeVirtual();
					if(actualTime != null) {
						int actualYearMonth = LocalDateTimeUtils.toIntYearMonth(actualTime.getYear(),actualTime.getMonthValue());
						if(actualYearMonth < yearMonth) {
							resList.add(detail);
							continue;
						}else {
							continue;
						}
					}
					
					LocalDateTime planTime = detail.getSupplyDate();
					if(planTime != null) {
						int planYearMonth = LocalDateTimeUtils.toIntYearMonth(planTime.getYear(),planTime.getMonthValue());
						if(planYearMonth < yearMonth) {
							resList.add(detail);
						}
					}
				}
			}
		}
		return resList;
	}
	
	/**
	 * 
	 * @Description：供货日期早于当前月楼栋
	 * @author：yyd
	 * @date：2020年3月6日 下午3:30:26
	 */
	private List<SupplyPlanVersionDetail> prepareActualbuildList(List<SupplyPlanVersionDetail> allBuildList, String month) {
		List<SupplyPlanVersionDetail> resList = Collections.synchronizedList(new ArrayList<>());
		int yearMonth = LocalDateTimeUtils.toIntYearMonth(Integer.parseInt(month.split("-")[0]), Integer.parseInt(month.split("-")[1]));
		for(SupplyPlanVersionDetail detail : allBuildList) {
			String type = detail.getType();
			 if(type.equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				 if(StrUtils.isNotEmpty(detail.getBusinessType()) && isValid(detail.getBusinessType())) {
					 LocalDateTime actualTime = detail.getSupplyTimeVirtual() == null ? detail.getSupplyDateActual() : detail.getSupplyTimeVirtual();
						if(actualTime != null) {
							int actualYearMonth = LocalDateTimeUtils.toIntYearMonth(actualTime.getYear(),actualTime.getMonthValue());
							if(actualYearMonth < yearMonth) {
								resList.add(detail);
								continue;
							}else {
								continue;
							}
						}
				 }
			 }
		}
		return resList;
	}

	/**
	 * 
	 * @Description：获取楼栋供货数据
	 * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
	 private List<MonthSupplyVO> prepareSupplyList(List<SupplyPlanVersionDetail> buildingList,String curYearMonth) {
		 List<MonthSupplyVO>  resList = Collections.synchronizedList(new ArrayList<>());
		 for(SupplyPlanVersionDetail detail : buildingList) {
			 MonthSupplyVO vo = new MonthSupplyVO();
			 vo.setBuildId(detail.getOrgId());
			 vo.setYearMonth(curYearMonth);
			 vo.setIsParking(detail.getIsParking());
			 
			 Integer isParking = detail.getIsParking();
			 LocalDateTime actualTime = detail.getSupplyTimeVirtual() == null?detail.getSupplyDateActual():detail.getSupplyTimeVirtual();
			 if(actualTime != null) {
				 if(isParking != null && isParking.intValue() == 1) {
					 vo.setParkingBldNum(detail.getParkingNumActual());
					 vo.setParkingBldPrice(detail.getNotCommodityValueActual());
				 }else {
					 vo.setHouseBldNum(detail.getRoomNumActual());
					 vo.setHouseBldArea(detail.getAreaActual());
					 vo.setHouseBldPrice(detail.getHouseCommodityValueActual());
				 }
			 }else {
				 if(isParking != null && isParking.intValue() == 1) {
					 vo.setParkingBldNum(detail.getParkingNum());
					 vo.setParkingBldPrice(detail.getNotCommodityValue());
				 }else {
					 vo.setHouseBldNum(detail.getRoomNum());
					 vo.setHouseBldArea(detail.getSaleArea());
					 vo.setHouseBldPrice(detail.getHouseCommodityValue()); 
				 }
			 }
			 
			 resList.add(vo);
		 }
		return resList;
	}
	 
	 
	 private List<ContractVO> prepareSignList(List<DmDmContractMonthDto> contractList,
				List<SupplyPlanVersionDetail> buildList, String curYearMonth) {
		 List<ContractVO> resList = Collections.synchronizedList(new ArrayList<>());
		 int yearMonth = LocalDateTimeUtils.toIntYearMonth(Integer.parseInt(curYearMonth.split("-")[0]), Integer.parseInt(curYearMonth.split("-")[1]));
		 for (SupplyPlanVersionDetail detail : buildList) {
			 String buildId = detail.getOrgId();
	         ContractVO vo = new ContractVO();
	         vo.setBuildId(buildId);
	         vo.setYearMonth(curYearMonth);
	         for(DmDmContractMonthDto m : contractList) {
	        	  if (buildId.equals(m.getBldPrdId())) {
	                    int ywgsDate = LocalDateTimeUtils.toIntYearMonth(m.getDYear(), m.getDMonth());
	                    if (ywgsDate < yearMonth) {
	                    	vo.setNum(NumberUtils.intADD(vo.getNum(), m.getTotalNum()));
	                    	vo.setCjRmbTotal(StrUtils.BigDecimalADD(vo.getCjRmbTotal(), m.getCjRmbTotal()));
	                    	vo.setBldArea(StrUtils.BigDecimalADD(vo.getBldArea(), m.getBldArea()));
	                    }
	              }
	         }
	         resList.add(vo);  
		 }
		return resList;
	}
	 
	 
	/**
     * 查询楼栋明源签约数据
     * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
    public List<ContractVO> prepareMymSignList(List<MymContractDto> mymSignList, List<SupplyPlanVersionDetail> buildings,String curYearMonth) {
    	List<ContractVO> resList = Collections.synchronizedList(new ArrayList<>());
    	//明源签约记录分类
    	List<MymContractDto> activationList = Collections.synchronizedList(new ArrayList<>());
		List<MymContractDto> closeList = Collections.synchronizedList(new ArrayList<>());
		List<MymContractDto> compensationList = Collections.synchronizedList(new ArrayList<>());
        for(int i = 0; i< mymSignList.size(); i++) {
        	String status = mymSignList.get(i).getStatus();
        	if(status.equals(ActivationEnum.ACTIVATION.getKey())) {
        		activationList.add(mymSignList.get(i));
        	}else if(status.equals(ActivationEnum.CLOSE.getKey())) {
        		closeList.add(mymSignList.get(i));
        	}
        }
        
        for(int j = 0; j< activationList.size(); j++) {
        	LocalDateTime auditDate = activationList.get(j).getAuditDate();
        	if(auditDate != null) {
        		compensationList.add(activationList.get(j));
        	}
        }
        
        
        int yearMonth = LocalDateTimeUtils.toIntYearMonth(Integer.parseInt(curYearMonth.split("-")[0]), Integer.parseInt(curYearMonth.split("-")[1]));

        for (SupplyPlanVersionDetail detail : buildings) {
        	String buildId = detail.getOrgId();
        	ContractVO vo = new ContractVO();
        	vo.setBuildId(buildId);
        	vo.setYearMonth(curYearMonth);
            for (MymContractDto m : mymSignList) {
                if (buildId.equals(m.getBldPrdID())) {
                    int ywgsDate = LocalDateTimeUtils.toIntYearMonth(m.getYwgsDate().getYear(), m.getYwgsDate().getMonthValue());
                    if (ywgsDate < yearMonth) {
                    	vo.setNum(NumberUtils.intADD(vo.getNum(), 1));
                    	vo.setCjRmbTotal(StrUtils.BigDecimalADD(vo.getCjRmbTotal(), m.getCjRmbTotal()));
                    	vo.setBldArea(StrUtils.BigDecimalADD(vo.getBldArea(), m.getBldArea()));
                    }
                }
            }
            //退房
            for (MymContractDto m : closeList) {
                if (buildId.equals(m.getBldPrdID())) {
                    int closeDate = LocalDateTimeUtils.toIntYearMonth(m.getCloseDate().getYear(), m.getCloseDate().getMonthValue());
                    if (closeDate < yearMonth) {
                    	vo.setNum(vo.getNum() - 1);
                    	vo.setCjRmbTotal(StrUtils.BigDecimalSub(vo.getCjRmbTotal(), m.getCjRmbTotal()));
                    	vo.setBldArea(StrUtils.BigDecimalSub(vo.getBldArea(), m.getBldArea()));
                    }
                }
            }
            //补差
            for (MymContractDto m : compensationList) {
                if (buildId.equals(m.getBldPrdID())) {
                    int ywgsDate = LocalDateTimeUtils.toIntYearMonth(m.getAuditDate().getYear(), m.getAuditDate().getMonthValue());
                    if (ywgsDate < yearMonth) {
                    	vo.setBcTotal(StrUtils.BigDecimalADD(vo.getBcTotal(), m.getBcTotal()));
                    	vo.setBcArea(StrUtils.BigDecimalADD(vo.getBcArea(), m.getBcArea()));
                    }
                }
            }
            resList.add(vo);  
        }
        return resList;
    }
    
    /**
     * 查询楼栋指定NOS签约数据
     * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
    public List<NosSignVO> getEarlyMonthNosSignList(List<NosTradedataDto> nosSignList, List<SupplyPlanVersionDetail> buildings,String curYearMonth) {
    	 List<NosSignVO> resList = Collections.synchronizedList(new ArrayList<>()); 
         //nos签约记录列表
         List<NosTradedataDto> signingList = new ArrayList<>(); 
         //nos退房记录列表
         List<NosTradedataDto> checkOutList = new ArrayList<>(); 
         //nos补差记录列表
         List<NosTradedataDto> compensationList = new ArrayList<>(); 
         for (NosTradedataDto nos : nosSignList) {
             String tradeStatus = nos.getTradeStatus();
             if (tradeStatus.equals(TradeStatusEnum.SIGNING.getKey())) {
                 signingList.add(nos);
             } else if (tradeStatus.equals(TradeStatusEnum.CHECK_OUT.getKey())) {
                 checkOutList.add(nos);
             } else if (tradeStatus.equals(TradeStatusEnum.COMPENSATION.getKey())) {
                 compensationList.add(nos);
             }
         }

         int yearMonth = LocalDateTimeUtils.toIntYearMonth(Integer.parseInt(curYearMonth.split("-")[0]), Integer.parseInt(curYearMonth.split("-")[1]));

         for (SupplyPlanVersionDetail obj : buildings) {
        	 String building = obj.getOrgId(); 
        	 NosSignVO dto = new NosSignVO();
        	 dto.setBuildId(building);
        	 dto.setYearMonth(curYearMonth);
        	 dto.setIsParking(obj.getIsParking());
             //签约
             for (NosTradedataDto n : signingList) {
                 if (building.equals(n.getBuildingId())) {
                     int tradeDate = LocalDateTimeUtils.toIntYearMonth(n.getTradeDate().getYear(), n.getTradeDate().getMonthValue());
                     if (tradeDate < yearMonth) {
                         dto.setRoomCount(dto.getRoomCount() + n.getRoomCount().intValue());
                         dto.setRoomArea(StrUtils.BigDecimalADD(dto.getRoomArea(), n.getRoomArea()));
                         dto.setTradeMoney(StrUtils.BigDecimalADD(dto.getTradeMoney(), n.getTradeMoney()));
                     }
                 }
             }
             //退房
             for (NosTradedataDto n : checkOutList) {
                 if (building.equals(n.getBuildingId())) {
                     int tradeDate = LocalDateTimeUtils.toIntYearMonth(n.getTradeDate().getYear(), n.getTradeDate().getMonthValue());
                     if (tradeDate < yearMonth) {
                         dto.setRoomCount(dto.getRoomCount() + n.getRoomCount().intValue());
                         dto.setRoomArea(StrUtils.BigDecimalADD(dto.getRoomArea(), n.getRoomArea()));
                         dto.setTradeMoney(StrUtils.BigDecimalADD(dto.getTradeMoney(), n.getTradeMoney()));
                     }
                 }
             }
             //补差
             for (NosTradedataDto n : compensationList) {
                 if (building.equals(n.getBuildingId())) {
                     int tradeDate = LocalDateTimeUtils.toIntYearMonth(n.getTradeDate().getYear(), n.getTradeDate().getMonthValue());
                     if (tradeDate < yearMonth) {
                         dto.setRoomCount(dto.getRoomCount() + n.getRoomCount().intValue());
                         dto.setRoomArea(StrUtils.BigDecimalADD(dto.getRoomArea(), n.getRoomArea()));
                         dto.setTradeMoney(StrUtils.BigDecimalADD(dto.getTradeMoney(), n.getTradeMoney()));
                     }
                 }
             }
             
             resList.add(dto);
         }
         
         return resList;
    }
    
    
    /**
     * 计算月初存货(供货-签约)
     * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
    public List<MonthInventoryVO> getMonthInventoryList(List<ContractVO> signList,List<MonthSupplyVO> supplyList,String curYearMonth) {
    	 List<MonthInventoryVO> resList = Collections.synchronizedList(new ArrayList<>()); 
    	 for(MonthSupplyVO supply : supplyList) {
    		MonthInventoryVO vo = new MonthInventoryVO();
     		vo.setBuildId(supply.getBuildId());
     		vo.setYearMonth(curYearMonth);
     		vo.setRoomNum(supply.getHouseBldNum());
    		vo.setParkingNum(supply.getParkingBldNum());
    		vo.setRoomArea(supply.getHouseBldArea());
    		vo.setHousePrice(supply.getHouseBldPrice());
    		vo.setParkingPrice(supply.getParkingBldPrice()); 
    		 
 			String supplyMonth = supply.getYearMonth();
 			String supplyBuildId = supply.getBuildId();
 			for(ContractVO sign : signList) {
 				String signMonth = sign.getYearMonth();
     			String signBuildId = sign.getBuildId();
     			if(supplyMonth.equals(signMonth) && supplyBuildId.equals(signBuildId)) {
     				if(supply.getIsParking() != null && supply.getIsParking().intValue() == 1) {
     					vo.setParkingNum(NumberUtils.subtract(supply.getParkingBldNum(),sign.getNum()));
     					vo.setParkingPrice(NumberUtils.subtract(supply.getParkingBldPrice(),NumberUtils.BigDecimalADD(4, sign.getBcTotal(), sign.getCjRmbTotal())));
     				}else {
     					vo.setRoomNum(NumberUtils.subtract(supply.getHouseBldNum(),sign.getNum()));
     					vo.setRoomArea(NumberUtils.subtract(supply.getHouseBldArea(),NumberUtils.BigDecimalADD(4, sign.getBcArea(), sign.getBldArea())));
     					vo.setHousePrice(NumberUtils.subtract(supply.getHouseBldPrice(),NumberUtils.BigDecimalADD(4, sign.getBcTotal(), sign.getCjRmbTotal())));
     				}
     			}
 			}
 			resList.add(vo);
 		}
    	return resList;
    }
    
    
    /**
     * 计算月初存货(供货-签约)
     * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
    public List<MonthInventoryVO> getMymMonthInventoryList(List<ContractVO> mymSignList,List<MonthSupplyVO> supplyList,List<SupplyPlanVersionDetail> buildingList,String curYearMonth) {
    	 List<MonthInventoryVO> resList = Collections.synchronizedList(new ArrayList<>()); 
    	 for(MonthSupplyVO supply : supplyList) {
    		MonthInventoryVO vo = new MonthInventoryVO();
     		vo.setBuildId(supply.getBuildId());
     		vo.setYearMonth(curYearMonth);
     		vo.setRoomNum(supply.getHouseBldNum());
    		vo.setParkingNum(supply.getParkingBldNum());
    		vo.setRoomArea(supply.getHouseBldArea());
    		vo.setHousePrice(supply.getHouseBldPrice());
    		vo.setParkingPrice(supply.getParkingBldPrice()); 
    		 
 			String supplyMonth = supply.getYearMonth();
 			String supplyBuildId = supply.getBuildId();
 			for(ContractVO sign : mymSignList) {
 				String signMonth = sign.getYearMonth();
     			String signBuildId = sign.getBuildId();
     			if(supplyMonth.equals(signMonth) && supplyBuildId.equals(signBuildId)) {
     				if(supply.getIsParking() != null && supply.getIsParking().intValue() == 1) {
     					vo.setParkingNum(NumberUtils.subtract(supply.getParkingBldNum(),sign.getNum()));
     					vo.setParkingPrice(NumberUtils.subtract(supply.getParkingBldPrice(),NumberUtils.BigDecimalADD(4, sign.getBcTotal(), sign.getCjRmbTotal())));
     				}else {
     					vo.setRoomNum(NumberUtils.subtract(supply.getHouseBldNum(),sign.getNum()));
     					vo.setRoomArea(NumberUtils.subtract(supply.getHouseBldArea(),NumberUtils.BigDecimalADD(4, sign.getBcArea(), sign.getBldArea())));
     					vo.setHousePrice(NumberUtils.subtract(supply.getHouseBldPrice(),NumberUtils.BigDecimalADD(4, sign.getBcTotal(), sign.getCjRmbTotal())));
     				}
     			}
 			}
 			resList.add(vo);
 		}
    	return resList;
    }
    
    /**
     * 查询Nos楼栋月初存货(供货-签约)
     * @author：yyd
	 * @date：2020年3月3日 下午9:19:16
	 */
    public List<MonthInventoryVO> getNosMonthInventoryList(List<NosSignVO> nosSignList,List<MonthSupplyVO> supplyList,List<SupplyPlanVersionDetail> buildingList,String curYearMonth) {
    	 List<MonthInventoryVO> resList = Collections.synchronizedList(new ArrayList<>()); 
    	 for(MonthSupplyVO supply : supplyList) {
     		MonthInventoryVO vo = new MonthInventoryVO();
      		vo.setBuildId(supply.getBuildId());
      		vo.setYearMonth(curYearMonth);
      		vo.setRoomNum(supply.getHouseBldNum());
     		vo.setParkingNum(supply.getParkingBldNum());
     		vo.setRoomArea(supply.getHouseBldArea());
     		vo.setHousePrice(supply.getHouseBldPrice());
     		vo.setParkingPrice(supply.getParkingBldPrice()); 
     		 
  			String supplyMonth = supply.getYearMonth();
  			String supplyBuildId = supply.getBuildId();
  			for(NosSignVO sign : nosSignList) {
  				String signMonth = sign.getYearMonth();
      			String signBuildId = sign.getBuildId();
      			if(supplyMonth.equals(signMonth) && supplyBuildId.equals(signBuildId)) {
      				if(supply.getIsParking() != null && supply.getIsParking().intValue() == 1) {
      					vo.setParkingNum(NumberUtils.subtract(supply.getParkingBldNum(),sign.getRoomCount()));
    					vo.setParkingPrice(NumberUtils.subtract(supply.getParkingBldPrice(),sign.getTradeMoney()));
      				}else {
      					vo.setRoomNum(NumberUtils.subtract(supply.getHouseBldNum(),sign.getRoomCount()));
    					vo.setRoomArea(NumberUtils.subtract(supply.getHouseBldArea(),sign.getRoomArea()));
    					vo.setHousePrice(NumberUtils.subtract(supply.getHouseBldPrice(),sign.getTradeMoney()));
      				}
      			}
  			}
  			resList.add(vo);
  		}
    	return resList;
    }
    
	/**
	 * 
	 * @Description：战规前（投资版）数据处理
	 * @author：yyd
	 * @date：2020年2月25日 下午4:08:17
	 */
	private List<SupplyPlanVersionDetail>  handleBeforeStrategyData(List<SupplyPlanVersionDetail> versionDetailList, String projectId) {
		List<SupplyPlanVersionDetail> resList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> productList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> batchList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> buildList =  Collections.synchronizedList(new ArrayList<>());
		Map<String, String> bMap = new HashMap<>();
		Map<String, String> pMap = new HashMap<>();
		
		for(SupplyPlanVersionDetail detail : versionDetailList) {
			 if(detail.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
				 String businessType = detail.getBusinessType();
				 if(StrUtils.isNotEmpty(businessType) && isValid(businessType)) {
					 pMap.put(detail.getId(), detail.getPid());
					 productList.add(detail);
				 }
			 }else if(detail.getType().equals(OrgTypeEunm.ORG_BATCH.getKey())){
				 bMap.put(detail.getId(), detail.getPid());
				 batchList.add(detail);
			 }else if(detail.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
				 detail.setPid(projectId);
				 resList.add(detail);
			 }else if(detail.getType().equals(OrgTypeEunm.ORG_GROUP.getKey())) {
				 resList.add(detail);
			 }
		}
		
		for(SupplyPlanVersionDetail product : productList) {
			for(Map.Entry<String, String> entry : bMap.entrySet()){
	            if(entry.getKey().equals(product.getPid())) {
	            	product.setPid(entry.getValue());
	            }
	        }
		}
		
		for(SupplyPlanVersionDetail product : productList) {
			for(Map.Entry<String, String> entry : pMap.entrySet()){
	            if(entry.getKey().equals(product.getId())) {
	            	for(SupplyPlanVersionDetail batch :batchList ) {
	            		if(batch.getId().equals(entry.getValue())) {
	            			SupplyPlanVersionDetail obj = new SupplyPlanVersionDetail();
	            			obj.setId(UUIDUtils.create());
	            			obj.setOrgId(batch.getOrgId());
	            			obj.setOrgCode(batch.getOrgCode());
	            			obj.setOrgName(batch.getOrgName());
	            			obj.setType(OrgTypeEunm.ORG_BUILD.getKey());
	            			obj.setPid(product.getId());
	            			obj.setBusinessType(product.getBusinessType());
	            			obj.setBusinessTypeName(product.getBusinessTypeName());
	            			obj.setFreeType(product.getFreeType());
	            			obj.setFreeTypeName(product.getFreeTypeName());
	            			obj.setProType(product.getProType());
	            			obj.setProTypeName(product.getProTypeName());
	            			obj.setProProductCode(product.getProProductCode());
	            			obj.setProProductType(product.getProProductType());
	            			
	            			obj.setSupplyDate(product.getSupplyDate());
	            			obj.setRoomNum(product.getRoomNum());
	            			obj.setParkingNum(product.getParkingNum());
	            			obj.setForsaleParkingNum(product.getForsaleParkingNum());
	            			obj.setSaleArea(product.getSaleArea());
	            			obj.setHouseCommodityValue(product.getHouseCommodityValue());
	            			obj.setNotCommodityValue(product.getNotCommodityValue());
	            			obj.setCommodityValue(product.getCommodityValue());
	            			
	            			buildList.add(obj);
	            		}
	            	}
	            	
	            }
	        }
		}
		
		resList.addAll(productList);
		resList.addAll(buildList);
		setSupplyOrgFullpath(resList,projectId);
		
		for(SupplyPlanVersionDetail obj : resList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				obj.setOrgNames(obj.getOrgFullPathName()+"-"+obj.getBusinessTypeName()+"-"+obj.getFreeTypeName()+"-"+obj.getProTypeName());
			}else {
				obj.setOrgNames(obj.getOrgFullPathName());
			}
		}
		
		List<SupplyPlanVersionDetail> uniqResList = resList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SupplyPlanVersionDetail::getOrgNames))), ArrayList::new)
        );
		
		Map<String, String> map = new HashMap<>();
		
		for(SupplyPlanVersionDetail obj : uniqResList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
				cleanPlanData(obj);
				map.put(obj.getOrgFullPathName(), obj.getId());
			}
		}
		
		for(SupplyPlanVersionDetail obj : uniqResList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				String fullPathName = obj.getOrgFullPathName();
				for(Map.Entry<String, String> entry : map.entrySet()){
					if(fullPathName.contains(entry.getKey())) {
						obj.setPid(entry.getValue());
					}
				}
			}
		}
		
		return uniqResList;
	}
	
	private void cleanPlanData(SupplyPlanVersionDetail resData) {
		resData.setNum(null);
		resData.setRoomNum(null);
		resData.setParkingNum(null);
		resData.setCommodityValue(null);
		resData.setHouseCommodityValue(null);
		resData.setNotCommodityValue(null);
		resData.setAveragePrice(null);
		resData.setAveragePriceParking(null);
		resData.setAveragePriceHouse(null);
		resData.setSaleArea(null);
		resData.setBusinessType(null);
		resData.setBusinessTypeName(null);
		resData.setFreeType(null);
		resData.setFreeTypeName(null);
		resData.setProType(null);
		resData.setProTypeName(null);
		resData.setSupplyDate(null);
	}
	/**
	 * 
	 * @Description：战规后数据处理
	 * @author：yyd
	 * @date：2020年2月25日 下午4:08:17
	 */
	private List<SupplyPlanVersionDetail> handleAfterStrategyData(List<SupplyPlanVersionDetail> list,String projectId) {
		List<SupplyPlanVersionDetail> resData = Collections.synchronizedList(new ArrayList<>());
		if(CollectionUtils.isNotEmpty(list)) {
			list.forEach(x->{
				String type = x.getType();
				if(type.equals(OrgTypeEunm.ORG_STAGE.getKey())) {
					x.setPid(projectId);
					cleanData(x);
					resData.add(x);
				}else if(type.equals(OrgTypeEunm.ORG_GROUP.getKey()) || type.equals(OrgTypeEunm.ORG_PRODUCT.getKey()) || type.equals(OrgTypeEunm.ORG_PRO_TYPE.getKey())) {
					cleanData(x);
					resData.add(x);
				}else if(type.equals(OrgTypeEunm.ORG_BUILD.getKey())) {
					if(StrUtils.isNotEmpty(x.getBusinessType()) && isValid(x.getBusinessType())) {
						resData.add(x);
					}
				}
			});
		}
		return resData;
	}
	
	private void cleanData(SupplyPlanVersionDetail obj) {
		obj.setNum(null);
		obj.setRoomNum(null);
		obj.setParkingNum(null);
		obj.setCommodityValue(null);
		obj.setHouseCommodityValue(null);
		obj.setNotCommodityValue(null);
		obj.setAveragePrice(null);
		obj.setAveragePriceParking(null);
		obj.setAveragePriceHouse(null);
		obj.setSaleArea(null);
		obj.setRoomNumActual(null);
		obj.setParkingNumActual(null);
		obj.setAreaActual(null);
		obj.setAveragePriceHouseActual(null);
		obj.setAveragePriceParkingActual(null);
		obj.setHouseCommodityValueActual(null);
		obj.setNotCommodityValueActual(null);
		obj.setCommodityValueActual(null);
	}
	
	/**
	 * 
	 * @Description：保存数据
	 * @author：yyd
	 * @date：2020年2月25日 下午4:08:17
	 */
	private List<DmDmSupplyMonthlyDetail> saveData(List<SupplyPlanVersionDetail> versionDetailList,SupplyPlanVersion dto,List<MonthInventoryVO> inventoryList,List<MonthInventoryVO> actualInventoryList,String versionMonth,String month,boolean flag,List<DmDmValueReport> reportList) {
		List<DmDmSupplyMonthlyDetail> dataList = Collections.synchronizedList(new ArrayList<>());
		for(SupplyPlanVersionDetail versionDetail : versionDetailList) {
			DmDmSupplyMonthlyDetail monthlyDetail = prepareDmDmSupplyMonthlyDetail();
			String projectId = dto.getProjectId(); 
			String versionType = dto.getVersionType();
    		String versionAttr = dto.getVersionAttr();
    		LocalDateTime supplyDate = versionDetail.getSupplyDate();
    		LocalDateTime supplyDateActure = versionDetail.getSupplyTimeVirtual() != null ? versionDetail.getSupplyTimeVirtual() : versionDetail.getSupplyDateActual();
    		
			monthlyDetail.setId(UUIDUtils.create());
			monthlyDetail.setProjectId(dto.getProjectId());
			monthlyDetail.setProjectCode(dto.getProjectCode());
			monthlyDetail.setProjectName(dto.getProjectName());
			
			monthlyDetail.setIsFirstOpen(getIsFirstOpen(dto.getProjectId(),reportList));
			monthlyDetail.setStageId(dto.getProjectfId());
			monthlyDetail.setStageCode(dto.getStageCode());
			monthlyDetail.setStageName(dto.getStageName());
			monthlyDetail.setEquityRatio(getEquityRatio(dto.getProjectfId(),reportList));
			monthlyDetail.setIsOpMarketing(getOpMarketing(dto.getProjectfId(),reportList));
			monthlyDetail.setPartNerIsAndTable(getIsAndTable(dto.getProjectfId(),reportList));
			monthlyDetail.setExistRoomSale(getIsExistRoomSale(dto.getProjectfId(),reportList));
			
			monthlyDetail.setVersionId(dto.getId());
			monthlyDetail.setSourcePriceVersionId(dto.getSourcePriceId());
			monthlyDetail.setVersionName(dto.getVersionName());
			monthlyDetail.setVersionNum(dto.getVersionNum());
			monthlyDetail.setVersionType(dto.getVersionType());
			monthlyDetail.setBudgetYear(dto.getBudgetYear());
			monthlyDetail.setVersionIdentify(dto.getVersionIdentify());
			monthlyDetail.setIsAssessmentVersion(dto.getIsAssessmentVersion());
			monthlyDetail.setVersionCreateTime(dto.getCreateTime());
			monthlyDetail.setVersionUpdateTime(dto.getUpdateTime());
			monthlyDetail.setVersionDate(versionMonth);
			monthlyDetail.setdId(versionDetail.getId());
			monthlyDetail.setOrgId(versionDetail.getOrgId());
			monthlyDetail.setOrgCode(versionDetail.getOrgCode());
			monthlyDetail.setOrgName(versionDetail.getOrgName());
			monthlyDetail.setOrgPid(versionDetail.getPid());
			monthlyDetail.setOrgType(versionDetail.getType());
			monthlyDetail.setProProductCode(versionDetail.getProProductCode());
			monthlyDetail.setProProductType(versionDetail.getProProductType());
			monthlyDetail.setBusinessType(versionDetail.getBusinessType());
			monthlyDetail.setBusinessTypeName(versionDetail.getBusinessTypeName());
			monthlyDetail.setFreeType(versionDetail.getFreeType());
			monthlyDetail.setFreeTypeName(versionDetail.getFreeTypeName());
			monthlyDetail.setProType(versionDetail.getProType());
			monthlyDetail.setProTypeName(versionDetail.getProTypeName());
			monthlyDetail.setIsParking(versionDetail.getIsParking());
			monthlyDetail.setCreateTime(LocalDateTime.now());
			if(versionDetail.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				monthlyDetail.setDesignBuildName(versionDetail.getOrgName());
				monthlyDetail.setBuildingName(getBuildingName(versionDetail.getOrgId(),reportList));
				String buildExistRoomSale = "";
				if(isBeforeStrategy(versionType,versionAttr)) {
					buildExistRoomSale = getBuildExistRoomSale(projectId,versionMonth,versionDetail.getProProductCode(),versionDetail.getOrgName(),reportList);
				}else {
					buildExistRoomSale = getBuildIsExistRoomSale(versionDetail.getOrgId(),reportList); 
				}
				monthlyDetail.setBuildExistRoomSale(buildExistRoomSale);
			}
			monthlyDetail.setSupplyDate(supplyDate);
			monthlyDetail.setSupplyDateActual(supplyDateActure);
			//月初存货
			monthlyDetail.setEarlyYear(month.split("-")[0]);
			monthlyDetail.setEarlyMonth(month.split("-")[1]);
			if(!flag) {
				if(versionDetail.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
					String buildId = versionDetail.getOrgId();
					for(MonthInventoryVO vo : inventoryList) {
						if(vo.getYearMonth().equals(month)) {
							if(vo.getBuildId().equals(buildId)) {
								monthlyDetail.setEarlyRoomCountHouse(vo.getRoomNum());
								monthlyDetail.setEarlyRoomAreaHouse(vo.getRoomArea());
								monthlyDetail.setEarlySumPriceHouse(vo.getHousePrice());
								monthlyDetail.setEarlyRoomCountParking(vo.getParkingNum());
								monthlyDetail.setEarlyRoomAreaParking(null);
								monthlyDetail.setEarlySumPriceParking(vo.getParkingPrice());
							}
						}
					}
					for(MonthInventoryVO vo : actualInventoryList) {
						if(vo.getYearMonth().equals(month)) {
							if(vo.getBuildId().equals(buildId)) {
								monthlyDetail.setEarlyRoomCountHouseActual(vo.getRoomNum());
								monthlyDetail.setEarlyRoomAreaHouseActual(vo.getRoomArea());
								monthlyDetail.setEarlySumPriceHouseActual(vo.getHousePrice());
								monthlyDetail.setEarlyRoomCountParkingActual(vo.getParkingNum());
								monthlyDetail.setEarlyRoomAreaParkingActual(null);
								monthlyDetail.setEarlySumPriceParkingActual(vo.getParkingPrice());
							}
						}
					}
					
				}
			}
			//计划供货
			SupplyPlanVersionDetail planObj = getPlanData(versionDetailList,versionDetail.getId(),month);
			monthlyDetail.setPlanSupplyYear(month.split("-")[0]);
			monthlyDetail.setPlanSupplyMonth(month.split("-")[1]);
			if(planObj != null) {
				monthlyDetail.setRoomNum(planObj.getRoomNum());
				monthlyDetail.setParkingNum(planObj.getParkingNum());
				monthlyDetail.setForsaleParkingNum(planObj.getForsaleParkingNum());
				monthlyDetail.setSaleArea(planObj.getSaleArea());
				monthlyDetail.setHouseCommodityValue(planObj.getHouseCommodityValue());
				monthlyDetail.setCommodityValue(planObj.getCommodityValue());
				monthlyDetail.setNotCommodityValue(planObj.getNotCommodityValue());
			}
			//实际供货
			SupplyPlanVersionDetail actualObj = getActualData(versionDetailList,versionDetail.getId(),month);
			monthlyDetail.setActualSupplyYear(month.split("-")[0]);
			monthlyDetail.setActualSupplyMonth(month.split("-")[1]);
			if(actualObj != null) {
				monthlyDetail.setRoomNumActual(actualObj.getRoomNumActual());
				monthlyDetail.setParkingNumActual(actualObj.getParkingNumActual());
				monthlyDetail.setForsaleParkingNumActual(actualObj.getForsaleParkingNumActual());
				monthlyDetail.setAreaActual(actualObj.getAreaActual());
				monthlyDetail.setHouseCommodityValueActual(actualObj.getHouseCommodityValueActual());
				monthlyDetail.setCommodityValueActual(actualObj.getCommodityValueActual());
				monthlyDetail.setNotCommodityValueActual(actualObj.getNotCommodityValueActual());
			}
			dataList.add(monthlyDetail);
		}
		
		return dataList;
	}
	
	private String getBuildExistRoomSale(String projectId, String versionMonth,String proProductCode,String buildName,List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(projectId.equals(report.getProjectId()) && versionMonth.equals(report.getEndDate()) 
						&& proProductCode.equals(report.getProductTypeCode()) && buildName.equals(report.getBuildingName())) {
					return  report.getIsProductExistRoomSale()+"";
				}
			}
		}
		return null;
	}

	private String getIsAndTable(String projectfId, List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(projectfId.equals(report.getProjectfId())) {
					return report.getIsAndTable()+"";
				}
			}
		}
		return "";
	}

	private String getOpMarketing(String projectfId, List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(projectfId.equals(report.getProjectfId())) {
					return report.getOpMarketing();
				}
			}
		}
		return "";
	}

	private String getEquityRatio(String projectfId, List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(projectfId.equals(report.getProjectfId())) {
					return report.getProjectfEquityRatio()+"";
				}
			}
		}
		return "";
	}

	private String getBuildIsExistRoomSale(String orgId,List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(orgId.equals(report.getBuildingId())) {
					return report.getIsProductExistRoomSale()+"";
				}
			}
		}
		return "";
	}

	private String getBuildingName(String orgId, List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(orgId.equals(report.getBuildingId())) {
					return report.getPhyBuildingName();
				}
			}
		}
		return "";
	}

	private String getIsExistRoomSale(String projectfId,List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(projectfId.equals(report.getProjectfId())) {
					return report.getIsExistRoomSale()+"";
				}
			}
		}
		return "";
	}

	private Integer getIsFirstOpen(String projectId,List<DmDmValueReport> reportList) {
		if(CollectionUtils.isNotEmpty(reportList)) {
			for(DmDmValueReport report : reportList) {
				if(StrUtils.isNotEmpty(report.getProjectId()) && projectId.equals(report.getProjectId())) {
					return report.getIsFirstOpen();
				}
			}
		}
		return null;
	}

	private DmDmSupplyMonthlyDetail prepareDmDmSupplyMonthlyDetail() {
		DmDmSupplyMonthlyDetail monthlyDetail = new  DmDmSupplyMonthlyDetail();
		monthlyDetail.setEarlyRoomCountHouse(0);
		monthlyDetail.setEarlyRoomAreaHouse(BigDecimal.ZERO);
		monthlyDetail.setEarlySumPriceHouse(BigDecimal.ZERO);
		monthlyDetail.setEarlyRoomCountParking(0);
		monthlyDetail.setEarlyRoomAreaParking(BigDecimal.ZERO);
		monthlyDetail.setEarlySumPriceParking(BigDecimal.ZERO);
		
		monthlyDetail.setRoomNum(0);
		monthlyDetail.setParkingNum(0);
		monthlyDetail.setForsaleParkingNum(0);
		monthlyDetail.setSaleArea(BigDecimal.ZERO);
		monthlyDetail.setHouseCommodityValue(BigDecimal.ZERO);
		monthlyDetail.setCommodityValue(BigDecimal.ZERO);
		monthlyDetail.setNotCommodityValue(BigDecimal.ZERO);
		
		monthlyDetail.setRoomNumActual(0);
		monthlyDetail.setParkingNumActual(0);
		monthlyDetail.setForsaleParkingNumActual(0);
		monthlyDetail.setAreaActual(BigDecimal.ZERO);
		monthlyDetail.setHouseCommodityValueActual(BigDecimal.ZERO);
		monthlyDetail.setCommodityValueActual(BigDecimal.ZERO);
		monthlyDetail.setNotCommodityValueActual(BigDecimal.ZERO);
		
		return monthlyDetail;
	}
	
	private SupplyPlanVersionDetail getPlanData(List<SupplyPlanVersionDetail> versionDetailList,String id,String yearMonth) {
		for(SupplyPlanVersionDetail detail : versionDetailList) {
			if(detail.getId().equals(id)) {
				LocalDateTime planDate = detail.getSupplyDate();
				if(planDate != null) {
					String planDateStr = LocalDateTimeUtils.formatTime(planDate, "yyyy-MM");
					if(planDateStr.equals(yearMonth)) {
						LocalDateTime actualDate = detail.getSupplyTimeVirtual() == null ? detail.getSupplyDateActual() : detail.getSupplyTimeVirtual(); 
						if(isForwardSupply(planDate,actualDate)) {
							return null;
						}
						return detail;
					}
				}
			}
		}
		return null;
	}
	
	private boolean isForwardSupply(LocalDateTime planDate,LocalDateTime actualDate) {
		 if(actualDate == null) {
			return false;
		 }
		 int plan = LocalDateTimeUtils.toIntYearMonth(planDate.getYear(), planDate.getMonthValue());
		 int actual = LocalDateTimeUtils.toIntYearMonth(actualDate.getYear(), actualDate.getMonthValue());
		 return actual < plan;
	}
	
	
	private SupplyPlanVersionDetail getActualData(List<SupplyPlanVersionDetail> versionDetailList,String id,String yearMonth) {
		for(SupplyPlanVersionDetail detail : versionDetailList) {
			if(detail.getId().equals(id)) {
				LocalDateTime actualDate = detail.getSupplyTimeVirtual() == null ? detail.getSupplyDateActual() : detail.getSupplyTimeVirtual();
				if(actualDate != null) {
					String actualDateStr = LocalDateTimeUtils.formatTime(actualDate, "yyyy-MM");
					if(actualDateStr.equals(yearMonth)) {
						return detail;
					}
				}
			}
		}
		return null;
	}
	
	/***
	 * 
	 * @Description：判断最新版本是否是战规前版本
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	public boolean isBeforeStrategy(String versionType,String versionAttr) {
		boolean flag = false;
		if(StrUtils.isNotEmpty(versionAttr)) {
			if(versionAttr.equals(VersionAttrEnum.BEFORE_WARPLAN.getKey())) {
				flag = true;
			}
		}else {
			if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
				flag = true;
			}
		}
		return flag;
	}
	
	/***
	 * 
	 * @Description：判断数据是否有效
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private boolean isValid(String businessType) {
		return businessType.equals(SalyTypeEnum.SALABLE.getKey()) || businessType.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey());
	}
	
	/***
	 * 
	 * @Description：初始化月份
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private static List<String> getMonths(String year) {
		  List<String>  months = Collections.synchronizedList(new ArrayList<>());
		  int currentMonth = LocalDateTime.now().getMonthValue();
		  int currentYear = LocalDateTime.now().getYear();
		  for(int i = Constants.ONE;i <= Constants.TWELVE; i++) {
			  if(year.equals(currentYear+"")) {
				  if(i <= currentMonth) {
					  if(i<10) {
			    		  months.add(year+"-0"+i);
			    	  }else {
			    		  months.add(year+"-"+i);
			    	  }  
				  }
			  }else {
				  if(i<10) {
		    		  months.add(year+"-0"+i);
		    	  }else {
		    		  months.add(year+"-"+i);
		    	  }  
			  }
	      }
		  return months;
	 }
	
	private static List<String> getMonthsTwo(List<Integer> years) {
		 List<String>  months = Collections.synchronizedList(new ArrayList<>());
		 for(Integer year : years) {
			 for(int i = Constants.ONE;i <= Constants.TWELVE; i++) {
				  if(i<10) {
		    		  months.add(year+"-0"+i);
		    	  }else {
		    		  months.add(year+"-"+i);
		    	  }  
		      } 
		 }
		 return months;
	 }
	
	/***
	 * 
	 * @Description：战规前（投资版）数据处理
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	@Override
	public List<SupplyPlanVersionDetail> handleInvestment(String versionId) {
		List<SupplyPlanVersionDetail> versionDetailList = supplyPlanVersionDetailMapper.selectByVersionId(versionId, IsDeleteEnum.NO.getKey());
		
		List<SupplyPlanVersionDetail> resList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> productList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> batchList =  Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> buildList =  Collections.synchronizedList(new ArrayList<>());
		Map<String, String> bMap = new HashMap<>();
		Map<String, String> pMap = new HashMap<>();
		
		for(SupplyPlanVersionDetail detail : versionDetailList) {
			 if(detail.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
				 String  buss = detail.getBusinessType();
				 if(StrUtils.isNotEmpty(buss) && isValid(buss)) {
					 pMap.put(detail.getId(), detail.getPid());
					 productList.add(detail);
				 }
			 }else if(detail.getType().equals(OrgTypeEunm.ORG_BATCH.getKey())){
				 bMap.put(detail.getId(), detail.getPid());
				 batchList.add(detail);
			 }else if(detail.getType().equals(OrgTypeEunm.ORG_STAGE.getKey()) || detail.getType().equals(OrgTypeEunm.ORG_GROUP.getKey())) {
				 resList.add(detail);
			 }
		}
		
		for(SupplyPlanVersionDetail product : productList) {
			for(Map.Entry<String, String> entry : bMap.entrySet()){
	            if(entry.getKey().equals(product.getPid())) {
	            	product.setPid(entry.getValue());
	            }
	        }
		}
		
		for(SupplyPlanVersionDetail product : productList) {
			for(Map.Entry<String, String> entry : pMap.entrySet()){
	            if(entry.getKey().equals(product.getId())) {
	            	for(SupplyPlanVersionDetail batch :batchList ) {
	            		if(batch.getId().equals(entry.getValue())) {
	            			SupplyPlanVersionDetail obj = new SupplyPlanVersionDetail();
	            			obj.setId(UUIDUtils.create());
	            			obj.setOrgId(batch.getOrgId());
	            			obj.setOrgCode(batch.getOrgCode());
	            			obj.setOrgName(batch.getOrgName());
	            			obj.setType(OrgTypeEunm.ORG_BUILD.getKey());
	            			obj.setPid(product.getId());
	            			obj.setBusinessType(product.getBusinessType());
	            			obj.setBusinessTypeName(product.getBusinessTypeName());
	            			obj.setFreeType(product.getFreeType());
	            			obj.setFreeTypeName(product.getFreeTypeName());
	            			obj.setProType(product.getProType());
	            			obj.setProTypeName(product.getProTypeName());
	            			obj.setRoomNum(product.getRoomNum());
	            			obj.setParkingNum(product.getParkingNum());
	            			obj.setForsaleParkingNum(product.getForsaleParkingNum());
	            			obj.setSaleArea(product.getSaleArea());
	            			obj.setHouseCommodityValue(product.getHouseCommodityValue());
	            			obj.setNotCommodityValue(product.getNotCommodityValue());
	            			obj.setCommodityValue(product.getCommodityValue());
	            			buildList.add(obj);
	            		}
	            	}
	            }
	        }
		}
		
		resList.addAll(productList);
		resList.addAll(buildList);
		setSupplyOrgFullpath(resList,Constants.ROOT_NODE_PID);
		
		for(SupplyPlanVersionDetail obj : resList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				obj.setOrgNames(obj.getOrgFullPathName()+"-"+obj.getBusinessTypeName()+"-"+obj.getFreeTypeName()+"-"+obj.getProTypeName());
			}else {
				obj.setOrgNames(obj.getOrgFullPathName());
			}
		}
		
		List<SupplyPlanVersionDetail> uniqResList = resList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SupplyPlanVersionDetail::getOrgNames))), ArrayList::new)
        );
		
		Map<String, String> map = new HashMap<>();
		
		for(SupplyPlanVersionDetail obj : uniqResList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
				cleanPlanData(obj);
				map.put(obj.getOrgFullPathName(), obj.getId());
			}
		}
		
		for(SupplyPlanVersionDetail obj : uniqResList) {
			if(obj.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
				String fullPathName = obj.getOrgFullPathName();
				for(Map.Entry<String, String> entry : map.entrySet()){
					if(fullPathName.contains(entry.getKey())) {
						obj.setPid(entry.getValue());
					}
				}
			}
		}
		
		return uniqResList;
	}
	
	/***
	 * 
	 * @Description：设置全路径
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private void setSupplyOrgFullpath(List<SupplyPlanVersionDetail> supplyPlanValueOrgList, String pid) {
		String fullPath ="";
		String fullPathName = "";
		for(SupplyPlanVersionDetail org : supplyPlanValueOrgList) {
			if(org.getId().equals(pid)) {
				fullPath= org.getOrgFullPath();
				fullPathName = org.getOrgFullPathName();
			}
		}
		for(SupplyPlanVersionDetail org : supplyPlanValueOrgList) {
			if(org.getPid().equals(pid)) {
				if(org.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
					org.setOrgFullPath(fullPath+"/"+org.getProProductCode()+"/"+org.getOrgCode());
					org.setOrgFullPathName(fullPathName+"/"+org.getProProductType()+"/"+org.getOrgName());
				}else {
					org.setOrgFullPath(fullPath+"/"+org.getOrgCode());
					org.setOrgFullPathName(fullPathName+"/"+org.getOrgName());
				}
				setSupplyOrgFullpath(supplyPlanValueOrgList,org.getId());
			}
		}
	}
	
	@Override
	public String getEndDate(String endDate) {
        return dmDmSupplyMonthlyDetailMapper.selectMaxVersionDate(endDate);
	}


	@Override
	public List<SupplyMonthlyDetailVO> querySupplyMonthlyDetail(String deadline,String userName) {
		log.info("###############查询月度供货明细表   Start: "+ LocalDateTime.now());
		String yearStr = deadline.split("-")[0];
		String monthStr = deadline.split("-")[1];
		List<SupplyMonthlyDetailVO> resList = Collections.synchronizedList(new ArrayList<>());
		long queryDataStart = System.currentTimeMillis();
		List<DmDmSupplyMonthlyDetail> versionDataList = dmDmSupplyMonthlyDetailMapper.selectDataList(deadline);
		if(CollectionUtils.isEmpty(versionDataList)) {
			versionDataList = dmDmSupplyMonthlyDetailMapper.selectHisDataList(deadline,yearStr,monthStr,StageStatusEnum.CTIVE.getKey());
		}
		long queryDataEnd = System.currentTimeMillis();
		log.info("###############查询明细数据耗时(毫秒):"+(queryDataEnd-queryDataStart));
		
		if(CollectionUtils.isEmpty(versionDataList)) {
			return resList;
		}
		List<ProjectByStages> allOrgList = dmDmSupplyCompareDetailMapper.selectProjectParentList();
		List<DmDmSupplyMonthlyDetail> projectList = prepareProjectList(userName,versionDataList);
		
		if(CollectionUtils.isNotEmpty(projectList)) {
			long setValueStart = System.currentTimeMillis();
			List<DmDmSupplyMonthlyDetail> resDataList = prepareMonthlyDeatilData(projectList,versionDataList);
			for(DmDmSupplyMonthlyDetail detail : resDataList) {
				SupplyMonthlyDetailVO vo = new SupplyMonthlyDetailVO();
				vo.setId(detail.getdId());
				vo.setCode(detail.getOrgCode());
				vo.setPid(detail.getOrgPid());
				vo.setType(detail.getOrgType());
				vo.setIsParking(detail.getIsParking());
				vo.setVersionType(VersionTypeEunm.getValueByKey(detail.getVersionType()));
			    if(detail.getOrgType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
					vo.setName(detail.getOrgName()+"("+prepareVersionName(detail)+")");
					//导出字段
					vo.setStageName(detail.getStageName());
					vo.setStageCode(detail.getStageCode());
					vo.setEquityRatio(detail.getEquityRatio());
					vo.setTradersWay(detail.getIsOpMarketing());
					vo.setIsMergeTable(detail.getPartNerIsAndTable());
					vo.setPendingHomeSale(detail.getExistRoomSale());
				}else if(detail.getOrgType().equals(OrgTypeEunm.ORG_GROUP.getKey())) {
					vo.setName(detail.getOrgName());
					vo.setGroupName(detail.getOrgName());
				}else if(detail.getOrgType().equals(OrgTypeEunm.ORG_PRO_TYPE.getKey())) {
					vo.setName(detail.getOrgName());
					//导出字段
					vo.setProductTypeName(detail.getOrgName());
					vo.setProductTypeCode(detail.getOrgCode());
				}else if(detail.getOrgType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
					vo.setName(detail.getOrgName());
					//导出字段
					vo.setProductTypeName(detail.getProProductType());
					vo.setProductTypeCode(detail.getProProductCode());
					vo.setProductName(detail.getOrgName());
					vo.setProductCode(detail.getOrgCode());
				}else if(detail.getOrgType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
					vo.setName(detail.getOrgName());
					//导出字段
					vo.setBulidNo(detail.getBuildingName());
					vo.setBulidNo2(detail.getDesignBuildName());
					vo.setPendingHomeSale2(detail.getBuildExistRoomSale());
					vo.setBusinessTypeName(detail.getBusinessTypeName());
					vo.setFreeTypeName(detail.getFreeTypeName());
					vo.setProTypeName(detail.getProTypeName());
				}
				
				SupplyMonthlyBaseValueVO inventory = new SupplyMonthlyBaseValueVO();
				inventory.setRoomNum(detail.getEarlyRoomCountHouse());
				inventory.setParkingNum(detail.getEarlyRoomCountParking());
				inventory.setSaleArea(detail.getEarlyRoomAreaHouse());
				inventory.setHousePrice(detail.getEarlySumPriceHouse());
				inventory.setParkingPrice(detail.getEarlySumPriceParking());
				inventory.setTotalPrice(NumberUtils.BigDecimalADD(4, detail.getEarlySumPriceHouse(), detail.getEarlySumPriceParking()));
				vo.setInventory(inventory);
				
				SupplyMonthlyBaseValueVO plan = new SupplyMonthlyBaseValueVO();
				plan.setRoomNum(detail.getRoomNum());
				plan.setParkingNum(detail.getParkingNum());
				plan.setSaleArea(detail.getSaleArea());
				plan.setHousePrice(detail.getHouseCommodityValue());
				plan.setParkingPrice(detail.getNotCommodityValue());
				plan.setTotalPrice(NumberUtils.BigDecimalADD(4, detail.getHouseCommodityValue(), detail.getNotCommodityValue()));
				plan.setSupplyDate(LocalDateTimeUtils.formatTime(detail.getSupplyDate(), "yyyy-MM-dd"));
				vo.setPlan(plan);
				
				SupplyMonthlyBaseValueVO actual = new SupplyMonthlyBaseValueVO();
				actual.setRoomNum(detail.getRoomNumActual());
				actual.setParkingNum(detail.getParkingNumActual());
				actual.setSaleArea(detail.getAreaActual());
				actual.setHousePrice(detail.getHouseCommodityValueActual());
				actual.setParkingPrice(detail.getNotCommodityValueActual());
				actual.setTotalPrice(NumberUtils.BigDecimalADD(4, detail.getHouseCommodityValueActual(), detail.getNotCommodityValueActual()));
				actual.setSupplyDate(LocalDateTimeUtils.formatTime(detail.getSupplyDateActual(), "yyyy-MM-dd"));
				vo.setActual(actual);	
				
				resList.add(vo);
			}
			long setValueEnd = System.currentTimeMillis();
			log.info("###############初始化层级数据耗时（毫秒）:"+(setValueEnd-setValueStart));
			
			long productStart = System.currentTimeMillis();
			//产品构成汇总
			collectData(resList,OrgTypeEunm.ORG_PRODUCT.getKey());
			long productEnd = System.currentTimeMillis();
			log.info("###############产品构成汇总耗时（毫秒）:"+(productEnd-productStart));
			//业态汇总
			collectData(resList,OrgTypeEunm.ORG_PRO_TYPE.getKey());
			
			//组团汇总
			collectData(resList,OrgTypeEunm.ORG_GROUP.getKey());
			
			//分期汇总
			collectData(resList,OrgTypeEunm.ORG_STAGE.getKey());
			
			//添加项目及以上层级
			addParentData(resList,allOrgList,projectList);
			
			//项目汇总
			collectData(resList,OrgTypeEunm.ORG_PRODUCTF.getKey());
			
			//城市公司汇总
			collectData(resList,OrgTypeEunm.ORG_CITY_COMPANY.getKey());
			
			//事业部汇总
			collectData(resList,OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
			
			//集团汇总
			collectData(resList,OrgTypeEunm.ORG_WANDA_GROUP.getKey());
			
			//计算均价
			for(SupplyMonthlyDetailVO vo : resList) {
				SupplyMonthlyBaseValueVO inventory = vo.getInventory();
				inventory.setHouseAvgPrice(NumberUtils.divide(inventory.getHousePrice(), inventory.getSaleArea(), 4));
				inventory.setParkingAvgPrice(NumberUtils.divide(inventory.getParkingPrice(),inventory.getParkingNum() == null ? null: new BigDecimal(inventory.getParkingNum()), 4));
				
				SupplyMonthlyBaseValueVO plan = vo.getPlan();
				plan.setHouseAvgPrice(NumberUtils.divide(plan.getHousePrice(), plan.getSaleArea(), 4));
				plan.setParkingAvgPrice(NumberUtils.divide(plan.getParkingPrice(),plan.getParkingNum() == null ? null: new BigDecimal(plan.getParkingNum()), 4));
				
				SupplyMonthlyBaseValueVO actual = vo.getActual();
				actual.setHouseAvgPrice(NumberUtils.divide(actual.getHousePrice(), actual.getSaleArea(), 4));
				actual.setParkingAvgPrice(NumberUtils.divide(actual.getParkingPrice(),actual.getParkingNum() == null ? null: new BigDecimal(actual.getParkingNum()), 4));
			}
		}
		log.info("###############查询月度供货明细表   end: "+ LocalDateTime.now());
		return resList;
	}

	private String prepareIsFirstOpen(Integer isFirstOpen) {
		if(isFirstOpen != null) {
			return isFirstOpen.intValue() == 0 ? "续销" : "首开";
		}
		return "";
	}

	/***
	 * 
	 * @Description：权限处理
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private List<DmDmSupplyMonthlyDetail> prepareProjectList(String userName,List<DmDmSupplyMonthlyDetail> list) {
		List<DmDmSupplyMonthlyDetail> projects = Collections.synchronizedList(new ArrayList<>());
		//获取数据权限
    	List<String> projectIds = prepareUserDataPermission(userName);
    	for(DmDmSupplyMonthlyDetail detail : list) {
    		String projectId = detail.getProjectId();
    		for(String str : projectIds) {
    			if(str.equals(projectId)) {
    				projects.add(detail);
    			}
    		}
    	}
    	//去重
    	List<DmDmSupplyMonthlyDetail> projectList = projects.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(DmDmSupplyMonthlyDetail::getProjectId))), ArrayList::new));

    	return projectList;
	}
	
	private List<DmDmSupplyMonthlyDetail> prepareMonthlyDeatilData(List<DmDmSupplyMonthlyDetail> projectList,List<DmDmSupplyMonthlyDetail> monthlyDeatilList) {
		List<DmDmSupplyMonthlyDetail> tempList = Collections.synchronizedList(new ArrayList<>());
		for(DmDmSupplyMonthlyDetail project : projectList) {
			for(DmDmSupplyMonthlyDetail detail : monthlyDeatilList) {
				if(project.getProjectId().equals(detail.getProjectId())) {
					tempList.add(detail);
				}
			}
		}
		return tempList;
	}
	
	/***
	 * 
	 * @Description：分期版本名称处理
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private String prepareVersionName(DmDmSupplyMonthlyDetail detail) {
		String versionName="";
		String versionType = detail.getVersionType();
		String versionTypeName = VersionTypeEunm.getValueByKey(versionType);
		String vesionNum = detail.getVersionNum();
		String lastDate = "";
		if(detail.getVersionUpdateTime() != null) {
			lastDate = LocalDateTimeUtils.formatTime(detail.getVersionUpdateTime(), "yyyyMMdd");
		}else {
			lastDate = LocalDateTimeUtils.formatTime(detail.getVersionCreateTime(), "yyyyMMdd");
		}
		if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey()) || versionType.equals(VersionTypeEunm.WARPLAN.getKey())) {
			String assessmentTag="";
			Integer isAssessmentVersion = detail.getIsAssessmentVersion();
			if(isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
				assessmentTag = "(考核版)";
			}
			versionName = versionTypeName+vesionNum+"-"+lastDate+assessmentTag;
		}else if(versionType.equals(VersionTypeEunm.BUDGET.getKey())) {
			if(StrUtils.isEmpty(detail.getVersionIdentify())) {
				versionName = detail.getBudgetYear()+"预算版"+vesionNum+"-"+lastDate;
			}else {
				if(detail.getVersionIdentify().equals(VersionIdentifyEnum.ALL_YEAR.getKey()) ||
						detail.getVersionIdentify().equals(VersionIdentifyEnum.MID_YEAR.getKey())	) {
					
					versionName = detail.getBudgetYear()+VersionIdentifyEnum.getValueByKey(detail.getVersionIdentify())+"预算版"+vesionNum+"-"+lastDate;
				}else {
					versionName = detail.getVersionIdentify()+vesionNum+"-"+lastDate;
				}
			}
		}else {
			String affiliationMonth = detail.getVersionDate();
			if(StrUtils.isNotEmpty(affiliationMonth)) {
				affiliationMonth = affiliationMonth.replace("-","");
			}
			versionName = affiliationMonth+"月动态版"+vesionNum+"-"+lastDate;
		}
		return versionName;
	}
	
	List<ProjectByStages> projectParentList = null;
	/***
	 * 
	 * @Description：项目及以上层级初始化
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private void addParentData(List<SupplyMonthlyDetailVO> resList, List<ProjectByStages> allOrgList,
			List<DmDmSupplyMonthlyDetail> projectList) {
		List<SupplyMonthlyDetailVO> dataList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyMonthlyDetailVO> list = Collections.synchronizedList(new ArrayList<>());
		for(DmDmSupplyMonthlyDetail project : projectList) {
			
			String projectId=project.getProjectId();
			projectParentList = Collections.synchronizedList(new ArrayList<>());
			getProjectParentLevel(projectId,allOrgList);
			
			ProjectByStages projectObj = getParentObj(projectParentList,projectId);
			if(projectObj != null) {
				//项目
				SupplyMonthlyDetailVO projectVo = new SupplyMonthlyDetailVO();
				projectVo.setId(project.getProjectId());
				projectVo.setCode(project.getProjectCode());
				projectVo.setName(project.getProjectName());
				projectVo.setIsFirst(prepareIsFirstOpen(project.getIsFirstOpen()));
				projectVo.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
				projectVo.setPid(projectObj.getParentOrgid());
				dataList.add(projectVo);
				//城市公司
				ProjectByStages city = getParentObj(projectParentList,projectObj.getParentOrgid());
				if(city != null) {
					SupplyMonthlyDetailVO cityVo = new SupplyMonthlyDetailVO();
					cityVo.setId(city.getOrgdepid());
					cityVo.setCode(null);
					cityVo.setName(city.getOrgname());
					cityVo.setType(OrgTypeEunm.ORG_CITY_COMPANY.getKey());
					cityVo.setPid(city.getParentOrgid());
					dataList.add(cityVo);
					//事业部
					ProjectByStages division = getParentObj(projectParentList,city.getParentOrgid());
					if(division != null) {
						SupplyMonthlyDetailVO divisionVo = new SupplyMonthlyDetailVO();
						divisionVo.setId(division.getOrgdepid());
						divisionVo.setCode(null);
						divisionVo.setName(division.getOrgname());
						divisionVo.setType(OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
						divisionVo.setPid(division.getParentOrgid());
						dataList.add(divisionVo);
					}
				}
			}
		}
		//集团
		for(ProjectByStages obj : allOrgList) {
			if(obj.getHrOrgTypeId().equals(HrOrgTypeEunm.ORG_11.getKey())) {
				SupplyMonthlyDetailVO allVo = new SupplyMonthlyDetailVO();
				allVo.setId(obj.getOrgdepid());
				allVo.setCode(null);
				allVo.setName(obj.getOrgname());
				allVo.setPid(Constants.ROOT_NODE_PID);
				allVo.setType(OrgTypeEunm.ORG_WANDA_GROUP.getKey());
				dataList.add(allVo);
				break;
			}
		}
		
		//去重
		list = dataList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SupplyMonthlyDetailVO::getId))), ArrayList::new)
        );
		
		resList.addAll(list);
	}
	
	private void getProjectParentLevel(String id,List<ProjectByStages> orgList){
		if(CollectionUtils.isNotEmpty(orgList)) {
			for(ProjectByStages org : orgList) {
				String orgId = org.getOrgdepid();
				if(orgId.equals(id)) {
					String pId = org.getParentOrgid();
					projectParentList.add(org);
					getProjectParentLevel(pId,orgList);
				}
			}
		}
	}
	
	/***
	 * 
	 * @Description：层级数据汇总
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private void collectData(List<SupplyMonthlyDetailVO> resList,String type) {
		for(SupplyMonthlyDetailVO vo : resList) {
			if(vo.getType().equals(type)) {
				List<SupplyMonthlyDetailVO> childList = getChildDataList(resList,vo.getId());
				collectChildData(childList,vo);
			}
		}
	}
	/***
	 * 
	 * @Description：将子级的数据汇总到父级
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private void collectChildData(List<SupplyMonthlyDetailVO> childList,SupplyMonthlyDetailVO parentObj) {
		if(CollectionUtils.isNotEmpty(childList)) {
			for(SupplyMonthlyDetailVO vo : childList) {
				SupplyMonthlyBaseValueVO inventory = vo.getInventory();
				SupplyMonthlyBaseValueVO plan = vo.getPlan();
				SupplyMonthlyBaseValueVO actual = vo.getActual();
				
				SupplyMonthlyBaseValueVO pInventory = parentObj.getInventory();
				SupplyMonthlyBaseValueVO pPlan = parentObj.getPlan();
				SupplyMonthlyBaseValueVO pActual = parentObj.getActual();
				//月初存货
				pInventory.setRoomNum(NumberUtils.intADD(pInventory.getRoomNum(),inventory.getRoomNum()));
				pInventory.setParkingNum(NumberUtils.intADD(pInventory.getParkingNum(),inventory.getParkingNum()));
				pInventory.setSaleArea(NumberUtils.BigDecimalADD(4,pInventory.getSaleArea(),inventory.getSaleArea()));
				pInventory.setHousePrice(NumberUtils.BigDecimalADD(4,pInventory.getHousePrice(),inventory.getHousePrice()));
				pInventory.setParkingPrice(NumberUtils.BigDecimalADD(4,pInventory.getParkingPrice(),inventory.getParkingPrice()));
				pInventory.setTotalPrice(NumberUtils.BigDecimalADD(4,pInventory.getTotalPrice(),inventory.getTotalPrice()));
				//供货计划
				pPlan.setRoomNum(NumberUtils.intADD(pPlan.getRoomNum(),plan.getRoomNum()));
				pPlan.setParkingNum(NumberUtils.intADD(pPlan.getParkingNum(),plan.getParkingNum()));
				pPlan.setSaleArea(NumberUtils.BigDecimalADD(4,pPlan.getSaleArea(),plan.getSaleArea()));
				pPlan.setHousePrice(NumberUtils.BigDecimalADD(4,pPlan.getHousePrice(),plan.getHousePrice()));
				pPlan.setParkingPrice(NumberUtils.BigDecimalADD(4,pPlan.getParkingPrice(),plan.getParkingPrice()));
				pPlan.setTotalPrice(NumberUtils.BigDecimalADD(4,pPlan.getTotalPrice(),plan.getTotalPrice()));
				//供货实际
				pActual.setRoomNum(NumberUtils.intADD(pActual.getRoomNum(),actual.getRoomNum()));
				pActual.setParkingNum(NumberUtils.intADD(pActual.getParkingNum(),actual.getParkingNum()));
				pActual.setSaleArea(NumberUtils.BigDecimalADD(4,pActual.getSaleArea(),actual.getSaleArea()));
				pActual.setHousePrice(NumberUtils.BigDecimalADD(4,pActual.getHousePrice(),actual.getHousePrice()));
				pActual.setParkingPrice(NumberUtils.BigDecimalADD(4,pActual.getParkingPrice(),actual.getParkingPrice()));
				pActual.setTotalPrice(NumberUtils.BigDecimalADD(4,pActual.getTotalPrice(),actual.getTotalPrice()));
			}
		}
	}
	/***
	 * 
	 * @Description：获取子级列表
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private List<SupplyMonthlyDetailVO> getChildDataList(List<SupplyMonthlyDetailVO> resList, String id) {
		List<SupplyMonthlyDetailVO> dataList = Collections.synchronizedList(new ArrayList<>());
		if(CollectionUtils.isNotEmpty(resList)) {
			for(SupplyMonthlyDetailVO obj : resList) {
				if(obj.getPid().equals(id)) {
					dataList.add(obj);
				}
			}
		}
		return dataList;
	}
	/***
	 * 
	 * @Description：获取用户的数据权限
	 * @author：yyd
	 * @date：2020年2月25日 下午2:32:43
	 */
	private List<String> prepareUserDataPermission(String userName) {
        List<String> projectIds = Collections.synchronizedList(new ArrayList<>());
        List<ProjectByStagesDto> dataPermissionList = idmUserService.queryUserDataPermissions(userName);
        if (CollectionUtils.isNotEmpty(dataPermissionList)) {
        	 for (ProjectByStagesDto dto : dataPermissionList) {
                 if (dto.getHrOrgTypeId().equals(HrOrgTypeEunm.ORG_31.getKey())) {
                     projectIds.add(dto.getOrgdepid());
                 }
             }
        } 
        return projectIds;
    }
	
	private ProjectByStages getParentObj(List<ProjectByStages> allOrgList,String pId) {
		if(CollectionUtils.isNotEmpty(allOrgList)) {
			for(ProjectByStages obj : allOrgList) {
				if(StrUtils.isNotEmpty(pId) && pId.equals(obj.getOrgdepid())) {
					return  obj;
				}
			}
		}
		return null;
	}
	
}
